package com.zxy.study.ui.opengl;

import android.util.Log;

import static android.opengl.GLES20.GL_COMPILE_STATUS;
import static android.opengl.GLES20.GL_FRAGMENT_SHADER;
import static android.opengl.GLES20.GL_LINK_STATUS;
import static android.opengl.GLES20.GL_VALIDATE_STATUS;
import static android.opengl.GLES20.GL_VERTEX_SHADER;
import static android.opengl.GLES20.glAttachShader;
import static android.opengl.GLES20.glCompileShader;
import static android.opengl.GLES20.glCreateProgram;
import static android.opengl.GLES20.glCreateShader;
import static android.opengl.GLES20.glDeleteProgram;
import static android.opengl.GLES20.glDeleteShader;
import static android.opengl.GLES20.glGetProgramInfoLog;
import static android.opengl.GLES20.glGetProgramiv;
import static android.opengl.GLES20.glGetShaderInfoLog;
import static android.opengl.GLES20.glGetShaderiv;
import static android.opengl.GLES20.glLinkProgram;
import static android.opengl.GLES20.glShaderSource;
import static android.opengl.GLES20.glValidateProgram;

/*
 *  @项目名：  study
 *  @包名：    com.zxy.study.ui.opengl
 *  @文件名:   ShaderHelper
 *  @创建者:   zhangxy
 *  @创建时间:  2019/8/12 13:51
 *  @描述：    TODO
 */
public class ShaderHelper {
	private static final String TAG = ShaderHelper.class.getSimpleName();

	public static int compileShader(int type, String shaderCode) {
		final int shareObjectId = glCreateShader(type);

		if (shareObjectId == 0) {
			Log.i(TAG, "compileShader: could not create new Shader");
		} else {
			glShaderSource(shareObjectId, shaderCode);
			glCompileShader(shareObjectId);

			final int[] compileStatus = new int[1];
			glGetShaderiv(shareObjectId, GL_COMPILE_STATUS, compileStatus, 0);

			Log.i(TAG, "compileShader: result of compile source \n" + shaderCode + " \n" + glGetShaderInfoLog(shareObjectId));
			if (compileStatus[0] == 0) {
				glDeleteShader(shareObjectId);
				Log.e(TAG, "compileShader: compile shader faile");
				return 0;
			}
		}

		return shareObjectId;
	}

	/**
	 * 创建顶点着色器
	 * @param shaderCode
	 * @return
	 */
	public static int compileVertexShader(String shaderCode) {
		return compileShader(GL_VERTEX_SHADER, shaderCode);
	}

	/**
	 * 创建片段着色器
	 * @param shaderCode
	 * @return
	 */
	public static int compileFragmentShader(String shaderCode) {
		return compileShader(GL_FRAGMENT_SHADER, shaderCode);
	}

	public static int linkProgram(int vertexShaderId, int fragmentShaderId) {
		final int programObjectId = glCreateProgram();
		if (programObjectId == 0) {
			Log.i(TAG, "linkProgram: could not create new program");
			return 0;
		}

		//添加着色器到程序对象中
		glAttachShader(programObjectId, vertexShaderId);
		glAttachShader(programObjectId, fragmentShaderId);

		//将着色链接起来
		glLinkProgram(programObjectId);

		//获取链接状态，判断是否成功
		final int[] linkStatus = new int[1];
		glGetProgramiv(programObjectId, GL_LINK_STATUS, linkStatus, 0);

		Log.i(TAG, "linkProgram: result of link program:\n" + glGetProgramInfoLog(programObjectId));
		if (linkStatus[0] == 0) {
			glDeleteProgram(programObjectId);
			Log.i(TAG, "linkProgram: link of program failed");
			return 0;
		}

		return programObjectId;
	}

	public static int createProgram(String vertexCode, String fragmentCode) {
		int vertexObjectId = compileVertexShader(vertexCode);
		if (vertexObjectId == 0) {
			return 0;
		}
		int fragmentObjectId = compileFragmentShader(fragmentCode);
		if (fragmentObjectId == 0) {
			return 0;
		}
		return linkProgram(vertexObjectId, fragmentObjectId);
	}

	/**
	 * 判断当前的opengl状态是否有效
	 * @param programObjectId
	 * @return
	 */
	public static boolean validateProgram(int programObjectId) {
		glValidateProgram(programObjectId);

		final int[] validateStatus = new int[1];
		glGetProgramiv(programObjectId, GL_VALIDATE_STATUS, validateStatus, 0);

		Log.i(TAG, "validateProgram: result of validateprogram: " + validateStatus[0] + "\n" + glGetProgramInfoLog(programObjectId));

		return validateStatus[0] != 0;
	}

}
